/*
	file:Server.cpp
	author:luoo
	date:2015 04 11
*/
#include <pthread.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include <libxml/parser.h>
#include <string.h>
#include <stdlib.h>  
#include <errno.h>  
#include <netdb.h>
#include <unistd.h>
#include "ProxyThread.cpp"
#include "StorageThread.cpp"
using namespace std;

#define MAXDATASIZE 4098
#define CMSPORT 8086
#define MAXCONN_NUM 10

char *registeredcms = "";
char buf[ MAXDATASIZE];
int numbytes,new_fd,sockfd;
int pnumbytes,pnew_fd,psockfd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t sin_size;
char * rece;

const char * registeredmsg = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
                            <Envelope type=\"r_register\"> \
                                success \
                            </Envelope>";

ProxyThread *pt;
StorageThread *st;

//函数声明
int DecodeXml(char * buffer);
int InitConnection();



int main(int argc, char *argv[]){
    InitConnection();
    if ((sockfd = socket ( AF_INET , SOCK_STREAM , 0)) == - 1) {
        perror ("socket error");
    	return -1;
    }
    memset(&client_addr,0,sizeof(struct sockaddr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(CMSPORT);
    server_addr.sin_addr.s_addr = INADDR_ANY;
    if ( bind ( sockfd, (struct sockaddr *) & server_addr, sizeof (struct sockaddr)) == -1) {
    	perror ("bind error");
     	return -1;
    }
    printf("Server start listening...\n");
    if (listen(sockfd, MAXCONN_NUM) ==-1) {
    	perror("listen error");
    	pthread_exit((void *)-1);
    }

    while(1){
        sin_size = sizeof ( struct sockaddr_in );
        if ( ( new_fd = accept ( sockfd, (struct sockaddr *)&client_addr, &sin_size) ) == - 1) {
            perror ( "accept error" );
        }
        printf ( "CMSThread:got connection from %s\n" , inet_ntoa( client_addr. sin_addr) );

        while (1) {
            if ( ( numbytes = recv ( new_fd, buf, MAXDATASIZE, 0) ) == - 1) {
                perror ( "recv error" );
                return -1;
            }
            buf[numbytes] = '\0';
            if(strlen(buf) <= 0){
                break;
            }
            printf("received:%s\n",buf);
            DecodeXml(buf);

        }
        printf("Server: disconnect from %s\n",inet_ntoa( client_addr. sin_addr) );
        close(new_fd);
    }
    close(pnew_fd);

    return 0;
}


int InitConnection(){
    pt = new ProxyThread();
    st = new StorageThread();
    pt->InitConnection();
    st->InitConnection();
    pt->SRD(pt->registermsg);
    st->SRD(st->registermsg);
}



int DecodeXml(char * buffer){
    xmlDocPtr doc = xmlParseMemory(buffer,strlen(buffer));
    if (doc == NULL){
        return -1;
    }
    xmlNodePtr curNode = xmlDocGetRootElement(doc); //get root element
    if (curNode == NULL){
        xmlFreeDoc(doc);
        return -2;
    }
    if (xmlStrcmp(curNode->name, BAD_CAST "Envelope")){  //匹配Envelope
        xmlFreeDoc(doc);
        return -3;
    }
    if (xmlHasProp(curNode,BAD_CAST "type")){
        xmlChar * szAttr = xmlGetProp(curNode,BAD_CAST "type");
        cout <<"centerserver got a " << szAttr <<" command..."<< endl;

        if(!xmlStrcmp(szAttr,BAD_CAST "cregister")){  //匹配cmsregister
            registeredcms = inet_ntoa( client_addr. sin_addr);
            if ( send ( new_fd, registeredmsg , strlen(registeredmsg), 0) == - 1) { 
                perror ( "send error" ); 
            } 
            cout << "centerserver got a cmsserver registered from " <<registeredcms<<endl;
        }

        if(strcmp(registeredcms,inet_ntoa(client_addr.sin_addr))){  
            cout << "you has not registered! please register first...." <<endl;
        }else{

            if(!xmlStrcmp(szAttr,BAD_CAST "getrtspuri")){  //匹配getrtspuri
                rece = pt->SRD(buffer);
                if ( send ( new_fd, rece , strlen(rece), 0) == -1 && strlen(rece) > 0) { 
                    perror ( "send error" ); 
                    return -1; 
                }
            }

            if(!xmlStrcmp(szAttr,BAD_CAST "startstorage")){  //匹配startstorage
                rece = st->SRD(buffer);
                if ( send ( new_fd, rece , strlen(rece), 0) == -1 && strlen(rece) > 0) { 
                    perror ( "send error" ); 
                    return -1; 
                }
            }

            if(!xmlStrcmp(szAttr,BAD_CAST "stopstorage")){  //匹配stopstorage
                rece = st->SRD(buffer);
                if ( send ( new_fd, rece , strlen(rece), 0) == -1 && strlen(rece) > 0) { 
                    perror ( "send error" ); 
                    return -1; 
                }
            }
        }
        xmlFree(szAttr);
    }
}
